package com.stanyung.realtimeserver.codec;

import java.io.IOException;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.stanyung.realtimeserver.Constants;

/**
 * 
 * @author asd
 * @see {@link org.apache.mina.filter.codec.CumulativeProtocolDecoder}
 * 
 */
public class ChatProtocolDecoder implements ProtocolDecoder {
	
	private static final Logger logger = LoggerFactory.getLogger(ChatProtocolDecoder.class); 

	private static final String READ_BUFFER = "READ_BUFFER";
	private static final String READ_NEEDING = "READ_NEEDING";

	@Override
	public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
		int remaining = in.remaining();
		readRemaining(session, in, out, remaining);
	}

	private void readRemaining(IoSession session, IoBuffer in, ProtocolDecoderOutput out, int remaining) throws IOException {
		int needing = (Integer) session.getAttribute(READ_NEEDING, 0);
		byte[] buff;
		if (needing == 0) {
			if (remaining >= 4) {
				needing = in.getInt();
				logger.debug("新包，长度：" + needing);
				byte[] data = new byte[needing];
				session.setAttribute("READ_BUFFER", data);
				session.setAttribute("READ_NEEDING", needing);
				remaining -= 4;
				if (remaining > 0) {
					readRemaining(session, in, out, remaining);
				}
			} else {
				logger.debug("无效包，长度：" + remaining);
				buff = new byte[remaining];
				in.get(buff);
				session.removeAttribute("READ_BUFFER");
				session.setAttribute("READ_NEEDING", 0);
			}
		} else {
			byte[] data = (byte[]) session.getAttribute(READ_BUFFER);
			logger.debug("拼接包，所需长度：" + needing + ", 新到长度：" + remaining);
			int len = Math.min(needing, remaining);
			buff = new byte[len];
			in.get(buff);
			System.arraycopy(buff, 0, data, data.length - needing, len);
			needing -= len;
			session.setAttribute("READ_NEEDING", needing);
			remaining -= len;
			logger.debug("还需长度：" + needing + ", 未读长度：" + remaining);
			if (needing == 0) {
				if(data.length >= Constants.HEAD_LENGTH) {
					Packet packet = Packet.parse(data);
					out.write(packet);
				}
			}
			if (remaining > 0) {
				readRemaining(session, in, out, remaining);
			}
		}
	}
	
	@Override
	public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception {

	}

	@Override
	public void dispose(IoSession session) throws Exception {

	}

}
